#!/usr/bin/perl
use strict;
use warnings;
use File::Compare;
use Template;
use IPC::Run qw(run);

# some useful options (see below for full list)
my $config = {
#    INCLUDE_PATH => '/search/path',  # or list ref
#	INTERPOLATE  => 1,               # expand "$var" in plain text
	POST_CHOMP   => 1,               # cleanup whitespace
#	PRE_PROCESS  => 'header',        # prefix each template
	EVAL_PERL    => 1,               # evaluate Perl code blocks
};

my $outpath = '../snowballstem.github.io/';
print "Generating output in '$outpath'\n";

$ENV{PYTHONPATH} = 'pygments-snowball';
$ENV{PYTHONIOENCODING} = 'UTF-8';

my $code_path_prefix = 'code/';
my $code_path_suffix = '.sbl';
my $coderepo_path_prefix = '../snowball/algorithms/';

system("mkdir", "-p", $outpath) == 0 or die "Failed to ensure '$outpath' exists\n";

# Stuff that just gets copied over.
foreach my $f (qw(
    CNAME
    favicon.ico
    robots.txt
    snub-dodecahedron.gif
    styles.css
    js
    codesets
    algorithms
    otherapps
    texts
    runtime
    compiler
)) {
    system("rm", "-rf", $outpath.$f) == 0 or die "Failed to delete '$outpath$f'\n";
    system("cp", "-a", $f, $outpath.$f) == 0 or die "Failed to copy '$f'\n";
}

# Currently needed for .tt files in algorithms - can be removed once we
# generate everything there.
system('find', $outpath, '-name', '*.tt', '-o', '-name', '*.gv', '-delete') == 0 or die "Failed to remove .tt files from generated website\n";

my $template = Template->new($config);

1;
# define template variables for replacement
my $vars = {};

# For stemming demo: FIXME: Dynamically generate this from UnicodeData
$$vars{word_regexp} = 'A-Za-z\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376-\u037D\u037F-\u0383\u0386\u0388-\u03F5\u03F7-\u0481\u048A-\u0559\u0561-\u0588\u05D0-\u05F2\u0620-\u064A\u066E-\u066F\u0671-\u06D3\u06D5\u06E5-\u06E6\u06EE-\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1-\u07BF\u07CA-\u07EA\u07F4-\u07F5\u07FA-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08E2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u09BB\u09BD\u09CE-\u09D6\u09DC-\u09E1\u09F0-\u09F1\u0A05-\u0A3B\u0A59-\u0A65\u0A72-\u0A74\u0A85-\u0ABB\u0ABD\u0AD0-\u0AE1\u0AF9-\u0B00\u0B05-\u0B3B\u0B3D\u0B5C-\u0B61\u0B71\u0B83-\u0BBD\u0BD0-\u0BD6\u0C05-\u0C3D\u0C58-\u0C61\u0C85-\u0CBB\u0CBD\u0CDE-\u0CE1\u0CF1-\u0D00\u0D05-\u0D3D\u0D4E-\u0D56\u0D5F-\u0D61\u0D7A-\u0D81\u0D85-\u0DC9\u0E01-\u0E30\u0E32-\u0E33\u0E40-\u0E46\u0E81-\u0EB0\u0EB2-\u0EB3\u0EBD-\u0EC7\u0EDC-\u0F00\u0F40-\u0F70\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065-\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10FA\u10FC-\u135C\u1380-\u138F\u13A0-\u13FF\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u1771\u1780-\u17B3\u17D7\u17DC\u1820-\u18A8\u18AA-\u191F\u1950-\u19CF\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4F\u1B83-\u1BA0\u1BAE-\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5-\u1CF7\u1D00-\u1DBF\u1E00-\u1FBC\u1FBE\u1FC2-\u1FCC\u1FD0-\u1FDC\u1FE0-\u1FEC\u1FF2-\u1FFC\u2071-\u2073\u207F\u2090-\u209F\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183-\u2184\u2C00-\u2CE4\u2CEB-\u2CEE\u2CF2-\u2CF8\u2D00-\u2D6F\u2D80-\u2DDF\u2E2F\u3005-\u3006\u3031-\u3035\u303B-\u303C\u3041-\u3098\u309D-\u309F\u30A1-\u30FA\u30FC-\u318F\u31A0-\u31BF\u31F0-\u31FF\u3400-\u4DBF\u4E00-\uA48F\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD-\uA8FF\uA90A-\uA925\uA930-\uA946\uA960-\uA97F\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5-\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB5A\uAB5C-\uABE2\uAC00-\uD7FF\uF900-\uFB1D\uFB1F-\uFB28\uFB2A-\uFBB1\uFBD3-\uFD3D\uFD50-\uFDFB\uFE70-\uFEFE\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFDF\u10000-\u100FF\u10280-\u102DF\u10300-\u1031F\u10330-\u10340\u10342-\u10349\u10350-\u10375\u10380-\u1039E\u103A0-\u103CF\u10400-\u1049F\u10500-\u1056E\u10600-\u10856\u10860-\u10876\u10880-\u108A6\u108E0-\u108FA\u10900-\u10915\u10920-\u1093E\u10980-\u109BB\u109BE-\u109BF\u10A00\u10A10-\u10A37\u10A60-\u10A7C\u10A80-\u10A9C\u10AC0-\u10AC7\u10AC9-\u10AE4\u10B00-\u10B38\u10B40-\u10B57\u10B60-\u10B77\u10B80-\u10B98\u10C00-\u10CF9\u11003-\u11037\u11083-\u110AF\u110D0-\u110EF\u11103-\u11126\u11150-\u11172\u11176-\u1117F\u11183-\u111B2\u111C1-\u111C4\u111DA\u111DC\u11200-\u1122B\u11280-\u112A8\u112B0-\u112DE\u11305-\u1133B\u1133D\u11350-\u11356\u1135D-\u11361\u11480-\u114AF\u114C4-\u114C5\u114C7-\u114CF\u11580-\u115AE\u115D8-\u115DB\u11600-\u1162F\u11644-\u1164F\u11680-\u116AA\u11700-\u1171C\u118A0-\u118DF\u118FF-\u123FF\u12480-\u16A5F\u16AD0-\u16AEF\u16B00-\u16B2F\u16B40-\u16B43\u16B63-\u16F50\u16F93-\u1BC9B\u1D400-\u1D6C0\u1D6C2-\u1D6DA\u1D6DC-\u1D6FA\u1D6FC-\u1D714\u1D716-\u1D734\u1D736-\u1D74E\u1D750-\u1D76E\u1D770-\u1D788\u1D78A-\u1D7A8\u1D7AA-\u1D7C2\u1D7C4-\u1D7CD\u1E800-\u1E8C6\u1EE00-\u1EEEF\u20000-\uE0000';

$$vars{highlight} = sub {
    my $in = shift;
    my $lang = shift;
    # Remove leading and trailing whitespace-only lines.
    $in =~ s/\A\s*\n//;
    $in =~ s/\n\s+\z/\n/;
    $in =~ /\&[#\w]+;/ and warn "HTML entity in Snowball code? [$&]";
    my $out;
    if (defined $lang) {
	run ['pygmentize', "-l$lang", '-fhtml'], \$in, \$out, \*STDERR
	    or die "python: $?";
    } else {
	run ['python', 'highlight_snowball.py'], \$in, \$out, \*STDERR
	    or die "python: $?";
    }
    return $out;
};

$$vars{highlight_inline} = sub {
    my $in = shift;
    # Remove leading and trailing whitespace-only lines.
    $in =~ s/\A\s*\n//;
    $in =~ s/\n\s+\z/\n/;
    $in =~ /\&[#\w]+;/ and warn "HTML entity in Snowball code? [$&]";
    $in =~ /\n/ and warn "Newline in inline Snowball code? [$in]";
    my $out;
    run ['python', 'highlight_snowball.py'], \$in, \$out, \*STDERR
	or die "python: $?";
    $out =~ s!<div([^.]*)><pre>!<span$1><code>!;
    $out =~ s!</pre></div>!</code></span>!;
    return $out;
};

$$vars{highlight_file} = sub {
    my $file = shift;
    if ($file =~ /\.\w+$/) {
	return scalar(`pygmentize -fhtml \Qcode/$file\E`);
    }
    my $source = "$code_path_prefix$file$code_path_suffix";
    my $corerepo_source = "$coderepo_path_prefix$file$code_path_suffix";
    if (-e $corerepo_source) {
	if (compare($corerepo_source, $source) != 0) {
	    print STDERR "warning: $source and $corerepo_source differ\n";
	}
    }
    return scalar(`python highlight_snowball.py < \Q$source\E`);
};

# <li> tags for a stemming algorithm.
$$vars{algorithm_lis} = sub {
    my ($id, $lang_name) = @_;
    my $out = << "__END__";
<li> <a href="https://raw.githubusercontent.com/snowballstem/snowball/master/algorithms/$id.sbl">The stemmer in Snowball</a></li>
<li> <a href="https://raw.githubusercontent.com/snowballstem/snowball-data/master/$id/voc.txt">Sample $lang_name vocabulary</a></li>
<li> <a href="https://raw.githubusercontent.com/snowballstem/snowball-data/master/$id/output.txt">Its stemmed equivalent</a></li>
__END__
    if (-f "algorithms/$id/stop.txt") {
	$out .= << "__END__";
<li> <a href="stop.txt">$lang_name stop word list (UTF-8 encoding)</a>
__END__
    }
    return $out;
};

$$vars{algorithm_vocab} = sub {
    my ($id, $voc1, $voc2) = @_;
    my (@out1, @out2);
    {
	my $i = join '', map{"$_\n"} @$voc1;
	my $o;
	run ['../snowball/stemwords', '-l', $id], \$i, \$o, \*STDERR
	    or die "../snowball/stemwords $?";
	chomp($o);
	@out1 = split /\n/, $o;
    }
    {
	my $i = join '', map{"$_\n"} @$voc2;
	my $o;
	run ['../snowball/stemwords', '-l', $id], \$i, \$o, \*STDERR
	    or die "../snowball/stemwords $?";
	chomp($o);
	@out2 = split /\n/, $o;
    }
    my $out = << "__END__";
<TABLE CELLPADDING=0>
<TR><TD>  <B>word</B> </TD>
 <TD></TD><TD> </TD>
 <TD></TD><TD> <B>stem</B> </TD>
 <TD></TD><TD>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
 <TD></TD><TD> <B>word</B> </TD>
 <TD></TD><TD> </TD>
 <TD></TD><TD> <B>stem</B> </TD>
</TR>

<TR><TD>
__END__
    for my $w (@$voc1) {
	$out .= $w . "<BR>\n";
    }
    $out .= << "__END__";
</TD>
<TD></TD><TD> <b>&#x21d2;</b> </TD>
<TD></TD><TD>
__END__
    for my $w (@out1) {
	$out .= $w . "<BR>\n";
    }
    $out .= << "__END__";
</TD>
<TD></TD><TD> </TD>
<TD></TD><TD>
__END__
    for my $w (@$voc2) {
	$out .= $w . "<BR>\n";
    }
    $out .= << "__END__";
</TD>
<TD></TD><TD> <b>&#x21d2;</b> </TD>
<TD></TD><TD>
__END__
    for my $w (@out2) {
	$out .= $w . "<BR>\n";
    }
    $out .= << "__END__";
</TD>
</TR>
</TABLE>
__END__
    return $out;
};

# The footer of the page.
# There should be no output after this.
$$vars{footer} = <<'__END__';
        </div><!-- /.col-md-10 -->
      </div><!-- /.row -->
    </div><!-- /.container -->

    <div class="container">
      <footer class="footer">
        <p>
          <a href="/lists.html">Write to our mailing list</a> if you have comments or questions about the project.
        </p>
      </footer>
    </div> <!-- /container -->
    <script src="https://cdn.jsdelivr.net/jquery/1.11.3/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/bootstrap/3.3.5/js/bootstrap.min.js"></script>
  </body>
</html>
__END__

my @menu = (
    [ "index" => "Introduction" ],
    [ "demo" => "Demo" ],
    [ "algorithms" => "Algorithms" ],
    [ "download" => "Download" ],
    [ "lists" => "Mailing Lists" ],
    [ "license" => "License" ],
    [ "credits" => "Credits" ],
    [ "projects" => "Projects" ]
);

    my @stemmer_js_files;
    my $stemmer_select = '<select id="lang" onchange="lang_changed(this);">';
    for (sort glob('js/*-stemmer.js')) {
	if (m!/(.*)-!) {
	    push @stemmer_js_files, $_;
	    if ($1 ne 'base') {
		my $default = $1 eq 'english' ? ' selected' : '';
		$stemmer_select .= "<option value='\u$1'$default>\u$1</option>";
	    }
	}
    }

run ['closure-compiler',
     qw(--compilation_level ADVANCED_OPTIMIZATIONS),
     qw(--warning_level VERBOSE),
     @stemmer_js_files],
     \undef, '>', $outpath."/js/stemmers.js", '2>', \*STDERR;

$stemmer_select .= "</select>";
$$vars{stemmer_js_files} = ['js/stemmers.js']; #\@stemmer_js_files;
$$vars{stemmer_select} = $stemmer_select;

# specify input filename, or file handle, text reference, etc.
for my $in (<*.tt */*.tt */*/*.tt>) {
    ((my $page = $in) =~ s/\.tt$//) or next;
    my $out = "$outpath$page.html";
    my $pretty_name = "\u$page";
    if ($page eq 'index') {
	$pretty_name = '';
    } elsif ($page eq 'lists') {
	$pretty_name = 'Mailing Lists';
    }

    my $menu = "<div class='list-group'>";
    my $found_entry = 0;
    for (@menu) {
	my ($link, $desc) = @{$_};
	my $class = 'list-group-item';
	if ($link eq $page || "$link/index" eq $page) {
	    $class .= ' active';
	    ++$found_entry;
	}
	if ($link eq "index") {
	    $link = '/';
	} elsif (-d $link) {
	    $link = "/$link/";
	} else {
	    $link = "/$link.html";
	}
	$menu .= '<a class="'.$class.'" href="'.$link.'">'.$desc.'</a>';
    }
    $menu .= <<'__END__';
<a class="list-group-item" href="https://github.com/snowballstem">Source on github</a><br>
</div>

<!--
<form NAME=P METHOD=GET ACTION="omega.cgi" TARGET="_top">
<center>
<input NAME=P VALUE="" SIZE=12>
<input TYPE=SUBMIT VALUE="Search" BORDER=0>
<input TYPE=hidden NAME=DB VALUE="snowball-website">
<input TYPE=hidden NAME=FMT VALUE="snquery">
</form>
<br>
-->

__END__
    # FIXME: Sort out sub-level navigation.
    if ($found_entry > 1) {
	print "$in: error: $found_entry menu entries highlighted\n";
	$menu = '';
    } elsif ($found_entry == 0) {
	print "$in: warning: No corresponding menu entry\n";
	$menu = '';
    }

    # $default title is the title of the page if one isn't explicitly specified.
    my $default_title;
    if ($pretty_name eq "") {
	$pretty_name = "Snowball";
    } else {
	$default_title = $pretty_name;
    }
    # This should be output first.
    $$vars{header} = sub {
	my $title = shift // $default_title;
	my $heading = $title;
	if (defined $title) {
	    $title .= ' - Snowball';
	} else {
	    $heading = $title = 'Snowball';
	}
	$title =~ s/\&/\&amp;/g;
	$title =~ s/</\&lt;/g;
	$title =~ s/>/\&gt;/g;
	return <<__END__;
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href="/favicon.ico">
    <title>$title</title>
    <link href="https://cdn.jsdelivr.net/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet">
    <link href="/styles.css" rel="stylesheet">
    <!--[if lt IE 9]>
      <script src="https://cdn.jsdelivr.net/html5shiv/3.7.3/html5shiv.min.js"></script>
      <script src="https://cdn.jsdelivr.net/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
  </head>

  <body>

    <!-- Static navbar -->
    <nav class="navbar navbar-default navbar-static-top">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a href="/" class="pull-left"><img src="/snub-dodecahedron.gif" style="margin: 4px; height: 42px;"></a>
          <a class="navbar-brand" href="/">Snowball</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
          <ul class="nav navbar-nav">
            <li><a href="/">Home</a></li>
            <li><a href="/credits.html">Credits</a></li>
          </ul>
	  <span id="forkongithub"><a href="https://github.com/snowballstem/snowball">Fork me on GitHub</a></span>
        </div><!--/.nav-collapse -->
      </div>
    </nav>

    <div class="container">
      <div class="row">
        <div class="col-md-2">
          $menu
        </div>
        <div class="col-md-10">
          <h1>$heading</h1>

__END__
    };
    my $out_str;
    $template->process($in, $vars, \$out_str) || die $template->error();
    # Kill empty <span> tags.
    $out_str =~ s!<span></span>!!g;
    open my $h_out, '>', $out or die $!;
    print $h_out $out_str or die $!;
    close $h_out or die $!;
}
for my $in (<*.gv */*.gv */*/*.gv>) {
    ((my $base = $in) =~ s/\.gv$//) or next;
    my $tmp = "$outpath$base.tmp.png";
    my $out = "$outpath$base.png";
    run ['neato', '-Tpng', $in], \undef, '>', $tmp, '2>', \*STDERR;
    run ['pngcrush', '-q', $tmp, $out], \undef, \*STDOUT, \*STDERR;
    unlink $tmp;
}
